using System;
using System.Web;
using System.Xml;

/*	-----------------------------------------------------------------------	
	Copyright:	umlungu consulting (pty) ltd
	Author:		Alan Benington
	Started:	2007-10-27
	Status:		beta
	Version:	2.0.0
	Build:		20071027
	License:	GNU General Public License
	-----------------------------------------------------------------------	*/

/*	-----------------------------------------------------------------------	
	Development Notes:
	==================
	20071027:	Start of .Net2 version from EmailX.1.0.2
	-----------------------------------------------------------------------	*/

namespace umlungu.engineX.emailX {
	/// <summary>
	/// The x_smtp class does raw smtp communication using tcpip sockets.
	/// <para>Additional information about the class</para>
	/// </summary>
	public class x_smtp {
		#region Invisible properties
		#endregion

		#region Visible properties
		private int port;
		/// <summary>SMTP port number</summary>
		/// <value>The port of the smtp server</value>
		public int Port {
			get {
				return port;
			}
			set {
				port = value;
			}
		}
		#endregion

		#region Constructors/Destructors
		/// <overloads>Constructor</overloads>
		/// <summary>Default constructor</summary>
		public x_smtp() {
			Port = 25;
		}
		/// <summary>Constructor description</summary>
		/// <param name="PortNumber">The port number of the smtp server</param>
		public x_smtp(int PortNumber) {
			Port = PortNumber;
		}
		#endregion

		#region Public methods
		/// <overloads>Send a mail message to a SMTP server</overloads>
		/// <summary>
		/// Description of this method overload
		/// </summary>
		/// <param name="From">email address of person sending the mail</param>
		/// <param name="To">email of recipient(s)</param>
		/// <param name="Subject">This is the email subject</param>
		/// <param name="message">The actual message to be sent</param>
		/// <param name="Username">The username for the account sending the message</param>
		/// <param name="Password">The password for the account sending the message</param>
		/// <param name="ServerName">The name of the SMTP server</param>
		public bool SendMail(string From, string To, string Subject, string message, string Username, string Password, string ServerName) {
			//Init Vars
			System.Text.ASCIIEncoding Encoder = new System.Text.ASCIIEncoding();
			x_tcpcom SmtpServer = new x_tcpcom();
			string SmtpReply = null;
			string CurMsg = null;
			System.DateTime CurTime;

			try {
				//Connect to server
				if (SmtpServer.Connect(ServerName,Port) == false) {
					throw new x_exception("error_smtp_connect", "Error Connection to SMTP Server");
				}

				//Wait for response
				CurTime = System.DateTime.Now;
				CurTime = CurTime.AddSeconds(10);
				while (CurTime > DateTime.Now & SmtpServer.DataWaiting == false) {
				}

				//check for connect
				CurMsg = null;
				while ((SmtpReply=SmtpServer.ReadData()) != null) {
					CurMsg += SmtpReply;
				}
				if (CurMsg.IndexOf("220") == -1) {
					throw new x_exception("error_smtp_connect220", "Error Connecting to SMTP Server");
				}
			
				//Send greeting (ehlo)
				SmtpServer.SendData("ehlo\r\n");

				//Wait for response
				CurTime = System.DateTime.Now;
				CurTime = CurTime.AddSeconds(10);
				while (CurTime > DateTime.Now & SmtpServer.DataWaiting == false) {
				}

				//Check for OK message..
				CurMsg = null;
				while ((SmtpReply=SmtpServer.ReadData()) != null)
				{
					CurMsg += SmtpReply;
				}
				if (CurMsg.IndexOf("250") == -1)
				{
					throw new x_exception("error_smtp_ehlo", "Error Talking to SMTP Server");
				}
			
				//Send auth Command (auth login)
				SmtpServer.SendData("auth login\r\n");

				//Wait for response
				CurTime = System.DateTime.Now;
				CurTime = CurTime.AddSeconds(10);
				while (CurTime > DateTime.Now & SmtpServer.DataWaiting == false)
				{
				}

				//Check for user name Challenge (334 VXNlcm5hbWU6)
				CurMsg = null;
				while ((SmtpReply=SmtpServer.ReadData()) != null)
				{
					CurMsg += SmtpReply;
				}
				if (CurMsg.IndexOf("334 VXNlcm5hbWU6") == -1)
				{
					if (CurMsg.StartsWith("502 Command is locally disabled"))
						goto NoLogin;
					if (CurMsg.StartsWith("504"))
						throw new x_exception("error_smtp_auth", "Cannot authenticate. Server must allow basic authentication");
					else
						throw new x_exception("error_smtp_auth", string.Concat("Error Talking to SMTP Server (", CurMsg, ")"));
				}

				//Send username (from 64bit encoded)
				string EncodedUser = Convert.ToBase64String(Encoder.GetBytes(Username));
				SmtpServer.SendData(EncodedUser+"\r\n");

				//Wait for response
				CurTime = System.DateTime.Now;
				CurTime = CurTime.AddSeconds(10);
				while (CurTime > DateTime.Now & SmtpServer.DataWaiting == false)
				{
				}

				//check for Password challenge (334 UGFzc3dvcmQ6)
				CurMsg = null;
				while ((SmtpReply=SmtpServer.ReadData()) != null)
				{
					CurMsg += SmtpReply;
				}
				if (CurMsg.IndexOf("334 UGFzc3dvcmQ6") == -1)
				{
					throw new x_exception("error_smtp_password", "Error Talking to SMTP Server");
				}

				//Send Password (Password 64bit encoded)
				string EncodedPass = Convert.ToBase64String(Encoder.GetBytes(Password));
				SmtpServer.SendData(EncodedPass+"\r\n");

				//Wait for response
				CurTime = System.DateTime.Now;
				CurTime = CurTime.AddSeconds(10);
				while (CurTime > DateTime.Now & SmtpServer.DataWaiting == false)
				{
				}

				//Check for Auth accepted.. (235 LOGIN authentication successful)
				CurMsg = null;
				while ((SmtpReply=SmtpServer.ReadData()) != null)
				{
					CurMsg += SmtpReply;
				}
				if (CurMsg.IndexOf("235") == -1)
				{
					throw new x_exception("error_smtp_login", "Error Authenticating to SMTP Server");
				}

			NoLogin:

				//**** Send Email ****
				//Send "MAIL FROM:" message
				SmtpServer.SendData("MAIL FROM: "+From+"\r\n");

				//Wait for Resonce
				CurTime = System.DateTime.Now;
				CurTime = CurTime.AddSeconds(10);
				while (CurTime > DateTime.Now & SmtpServer.DataWaiting == false)
				{
				}

				//check responce
				CurMsg = null;
				while ((SmtpReply=SmtpServer.ReadData()) != null)
				{
					CurMsg += SmtpReply;
				}
				if (CurMsg.IndexOf("250") == -1)
				{
					throw new x_exception("error_smtp_from", String.Concat("Error with orgin address: ", From));
				}


				//Send "RCPT TO:" message
				SmtpServer.SendData("RCPT TO: "+To+"\r\n");

				//Wait for Resonce
				CurTime = System.DateTime.Now;
				CurTime = CurTime.AddSeconds(10);
				while (CurTime > DateTime.Now & SmtpServer.DataWaiting == false)
				{
				}

				//check responce
				CurMsg = null;
				while ((SmtpReply=SmtpServer.ReadData()) != null)
				{
					CurMsg += SmtpReply;
				}
				if (CurMsg.IndexOf("250") == -1)
				{
					throw new x_exception("error_smtp_rcpt", String.Concat("Error with Destination address: ", To));
				}

				//Send "DATA"
				SmtpServer.SendData("DATA\r\n");

				//Wait for Resonce
				CurTime = System.DateTime.Now;
				CurTime = CurTime.AddSeconds(10);
				while (CurTime > DateTime.Now & SmtpServer.DataWaiting == false)
				{
				}

				//check responce
				CurMsg = null;
				while ((SmtpReply=SmtpServer.ReadData()) != null)
				{
					CurMsg += SmtpReply;
				}
				if (CurMsg.IndexOf("354") == -1)
				{
					throw new x_exception("error_smtp_data", String.Concat("Error While trying to Send Email Subject & Body"));
				}

				//Send subject "Subject:"
				SmtpServer.SendData("Subject: "+Subject+"\r\n");

				//Send message
				SmtpServer.SendData("\r\n"+message+"\r\n");

				//Send "."
				SmtpServer.SendData(".\r\n");

				//Wait for Resonce
				CurTime = System.DateTime.Now;
				CurTime = CurTime.AddSeconds(10);
				while (CurTime > DateTime.Now & SmtpServer.DataWaiting == false)
				{
				}

				//check responce
				CurMsg = null;
				while ((SmtpReply=SmtpServer.ReadData()) != null)
				{
					CurMsg += SmtpReply;
				}
				if (CurMsg.IndexOf("250") == -1)
				{
					throw new x_exception("error_smtp_close", "Error while attempting to close message on server.");
				}

				//Close connection
				SmtpServer.Disconnect();

				return true;
			} catch (x_exception e) {
				throw new x_exception("error_smtp_send", String.Concat("Error Sending Email: ", e.Code, " :: ", e.Message));
			} catch (System.Exception e) {
				throw new x_exception("error_smtp_send", String.Concat("Error Sending Email: ", e.Message));
			}
		}
		#endregion
		
		#region Protected methods
		#endregion
				
		#region Private methods
		#endregion
	}
}
